﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using UtilZ.Dotnet.Ex.Base;
using UtilZ.Dotnet.Ex.ZLog;

namespace UtilZ.Dotnet.Ex.Communication.Net.Ftp
{
    /// <summary>
    /// 进入被动模式
    /// Enter passive mode.
    /// </summary>
    internal class FtpPASVCommand : FtpCommandAbs
    {
        /***********************************************************************************************************
        * [PASV]（Passive，被动的）命令
        * 说明：告诉服务器在一个非标准端口上收听数据连接。
        * 
        * 用法：PASV<CRLF>
        * 参数：这条命令请求server-DTP（服务器数据传送规约）“收听”某个数据端口（该端口不是它的默认数据端口），并等待一个连接而不是在收到传输命令时初始化一个连接。对这条命令的响应包括主机地址和此服务器正在收听的端口地址。
        * 例子：
        * SendData "PASV" + “/r/n
        * 
        * 返回值如下（粗体表示成功）：
        * 227  输入被动模式（h1,h2,h3,h4,p1,p2）。
        * 
        * 返回值包括一个在数据连接中使用的数据端口的HOST-PORT规约。此参数是一个32位Internet主机地地址和一个16位TCP端口地的拼 接。这个地址信息被拆分为8位的字段，并且每个字段的值是作为一个十进制数传输的（在字符串意义上）。H1是Internet主机地址的高位字节，p1是 端口地址的高位字节。
        * 421  服务不可用，关闭控制连接。
        * 
        * 如果某项服务获知自己即将关闭，会向所有命令做出这个应答。
        * 500  语法错误，无法识别命令。这其中包括命令行过长之类的错误。
        * 501  参数或变元中有语法错误。
        * 503  无法登录。
        * 
        ************************************************************************************************************/


        public FtpPASVCommand()
            : base()
        {

        }

        protected override string[] GetNames()
        {
            return new string[] { FtpCommands.PASV, FtpCommands.LPSV };
        }

        protected override IFtpResponse PrimitiveExcute(FtpSession session, string command, string commandLine)
        {
            //Request: PASV
            //Response: 227 Entering Passive Mode (192,168,1,20,192,20).

            try
            {
                switch (session.FtpServer.Config.WorkMode)
                {
                    case FtpWorkMode.Passive:
                    case FtpWorkMode.Mix:
                        break;
                    default:
                        return new FtpCodeResponse(FtpStatusCodes.Code502, "Command not excute.");
                }

                var dataTranfer = new FtpPassiveDataTranfer(session);
                session.SetDataTranferObject(dataTranfer);
                return dataTranfer.GetFtpResponse();
            }
            catch (Exception ex)
            {
                return new FtpCodeResponse(FtpStatusCodes.Code451, ex.Message);
            }
        }
    }

}
